#!/usr/bin/env perl

# word builder 0.1 - builds words out of text strings

use strict;
$| = 1;

use Storable;

use constant DICT_PATH => 'generated_dictionaries/dictionary.pl';

# dictionary_filename => powers of 2
# http://www.isc.ro/en/commands/lists.html
my %dict_masks = (
	twl06   => 1,
	sowpods => 2,
	ods     => 4,
	zynga   => 8,
);

my $dict_mask_all = 0; $dict_mask_all |= $_ for values %dict_masks;

{
my $dict_choice = shift;
$dict_choice =~ /help/i and print STDERR "Usage: $0 [" . join('|', keys %dict_masks) . "] [dictionary_path]\n" and exit 0;

my $dict_path = shift || DICT_PATH;
my $dict_mask = $dict_masks{lc $dict_choice} || $dict_mask_all;

print 'Loading ' . ($dict_mask == $dict_mask_all ? 'entire' : $dict_choice) . ' dictionary...';
open my $dict_file, '<', $dict_path or die $!;
my $dict = Storable::fd_retrieve($dict_file)->[0];

for(;;){
	print "\n\nLetters: ";

	# normalize input
	chomp(my $chars = lc <>);
	$chars =~ tr/a-z/~/c; # ~ sorts after a-z

	print join "\n",
		sort {length $b <=> length $a || $a cmp $b}
		&collect_words($dict, [sort {$a cmp $b} split '', $chars], $dict_mask);
}
}

sub collect_words {
	my($dict, $chars, $dict_mask) = @_;
	return unless defined $dict;

	my @collected;
	for my $d (@$dict){
		my @chars;
		my $matched;
		for(my $i=0; $i<=$#$chars; $i++){
			if($chars->[$i] ne '~'){
				my $cmp = $chars->[$i] cmp $d->[0];
				next if $cmp < 0;
				if($cmp > 0){
					# blanks are last
					if($chars->[-1] eq '~'){
						$i = $#$chars,
						next;
					}
					last;
				}
			}

			# take the matching letter out
			@chars = @$chars[0 .. $i - 1, $i + 1 .. $#$chars];
			$matched = !!1;
			last;
		}
		next unless $matched;

		push @collected, map $_->[1] & $dict_mask ? $_->[0] : (), @{$d->[1]};
		push @collected, collect_words($d->[2], \@chars, $dict_mask) if @chars;
	}

	return @collected;
}
